package DataStructures.linkedlist;

/**
 * @author ：ALi
 * @date ：Created in 2021/9/12 19:12
 * @description：单链表
 * @modified By：
 * @version: 尚硅谷java数据结构与算法$
 */
public class SingleLinkedListDemo {
    public static void main(String[] args){
        //创建节点对象
        HeroNode hero1 = new HeroNode(1,"松江1","及时雨1");
        HeroNode hero2= new HeroNode(3,"松江3","及时雨2");
        HeroNode hero3 = new HeroNode(5,"松江5","及时雨3");
        HeroNode hero4 = new HeroNode(7,"松江7","及时雨4");
        HeroNode hero5 = new HeroNode(5,"松江6","及时雨6");
        HeroNode hero6 = new HeroNode(6,"松江77","及时雨77");
        //创建链表管理对象
        SingleLinkedList List = new SingleLinkedList();
        //插入链表（尾插法）
        List.add(hero1);
        List.add(hero2);
        List.add(hero3);
        List.add(hero4);
        System.out.println("原来的顺序:");
        //打印链表
        List.show();
        System.out.println("顺序插入:");

        List.addOrderBy(hero5);
        List.show();

        //修改数据
        List.updata(hero6,"test");
        System.out.println("修改数据后:");

        List.show();

//        //删除节点
//        System.out.println("删除节点:");
//        List.delect(hero1);
//        List.delect(hero2);
//        List.delect(hero3);
//        List.delect(hero4);
//        List.show();

        //反转链表
       List.returnHeroNode(List.getHead());
       System.out.println("反转后的：");
       List.show();


    }

}

/**
 * SingleLinkedList is Administration List
 */
class SingleLinkedList{
    //创建头结点,不存数据(带头节点的链表)
    private HeroNode head = new HeroNode(0,"","");

    /**
     * get方法
     * @return 头结点
     */
    public HeroNode getHead() {
        return head;
    }

    /**
     * 增加新节点
     * @param node 新节点node
     */
    public void add(HeroNode node){
      //创建临时节点，用它来代替原来的头结点，保证原来的链表是不变的。单链表有了头结点，其他节点就都有了。
      HeroNode temp = head;
      //自己总是搞忘了！
      //找到最后一个节点，然后插入
      while(true){
          if (temp.next == null) {
              break;
          }
          temp = temp.next;

       }
       //此时temp指向链表的最后
        temp.next = node;

    }

    /**
     * 打印链表
     */
   public void show(){
        if (head.next == null){
            System.out.println("链表为空");
//            throw new RuntimeException("链表为空！");
        }
        HeroNode temp = head.next;
        while(temp != null){
            System.out.println(temp);
            temp = temp.next;
        }

    }

    /**
     * 按照顺序插入数据
     * @param node 新节点
     */
    public void addOrderBy(HeroNode node){
       HeroNode temp = head;
       if (temp == null)
           temp.next = node;
       while(temp != null){

           //判断节点的序号是否存在.存在bug，如果与插入节点相同的节点在后面，还是会插入。除非先遍历一遍或者链表有序
           if (temp.no == node.no || temp.next.no == node.no){
               System.out.printf("节点%d已存在\n",node.no);
               break;
           }

           if (temp.no < node.no && temp.next.no>node.no){
               node.next = temp.next;
               temp.next = node;
           }

           temp = temp.next;
           //新节点插在最后
           if(temp.next == null){
               temp.next = node;
               break;
           }
       }
    }

    /**
     *更新节点
     * @param node:要修改的节点
     * @param name:修改节点后的名字
     */
    public void updata(HeroNode node,String name){
        if (head.next == null){
            return;
        }
        HeroNode temp = head.next;
        boolean res = true;
        while(temp.no != node.no){
            if (temp.next == null){
                System.out.printf("没找到节点%s\n",node.Name);
                res = false;
                break;
            }
            temp = temp.next;
        }
        if(res){
            temp.Name = name;
        }else
            return;

    }

    /**
     * 删除节点
     * @param delectNode 要删除的节点
     */
    public void delect(HeroNode delectNode){
        HeroNode node = head;
        if (head.next == null){
            System.out.println("链表为空");
            return;
        }
        boolean res = true;
        while (res){
            if (node.next == null){
               System.out.printf("无%s节点\n",delectNode.Name);
               break;
            }
            if (node.next.no == delectNode.no){
                //就算要删除的节点是尾结点也可以删除
//                node.next = node.next.next;//这个也可以
                node.next = delectNode.next;
                break;
            }
            node = node.next;
        }
    }

    /**
     *
     * @param head 原节点的头
     * @return 反转后的链表
     */
    public void returnHeroNode(HeroNode head){
        if (head.next == null || head.next.next == null){
            return;
        }
        HeroNode newHead = new HeroNode(0,"","");

        HeroNode temp = head.next;
        //当前节点的下一个节点
        HeroNode next = null;//没有的话链表会断开

        while (temp != null) {
            next = temp.next;
            temp.next = newHead.next;
            newHead.next = temp;
            temp = next;
        }
        //为了调用其自身的打印方法。用下面的打印语句，就可以不用这一行代码了
        head.next = newHead.next;

//        //打印链表
//        System.out.println("反转后的：");
//        if (newHead.next == null){
//            System.out.println("链表为空");
////            throw new RuntimeException("链表为空！");
//        }
//        HeroNode temp2 = newHead.next;
//        while(temp2 != null){
//            System.out.println(temp2);
//            temp2 = temp2.next;
//        }
    }


}

/**
 * 节点类
 */
class HeroNode{
    public int no;
    public String Name;
    public String nickName;
    public HeroNode next;

    //构造器
    public HeroNode(int no, String Name, String nickName){
        this.no = no;
        this.Name = Name;
        this.nickName = nickName;
    }

    //重写toString方法
    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", Name='" + Name + '\'' +
                ", nickName='" + nickName + '\'' +
                '}';
    }

}